home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / libs / viewwrld / viewwrld.lha / viewworld / gr / animate.c next >
Encoding:
C/C++ Source or Header  |  1989-09-21  |  15.6 KB  |  533 lines

  1. /* $Id: animate.c,v 2.3 89/09/20 17:01:22 mbp Exp $
  2.  *
  3.  * animate.c: animation procedures
  4.  */
  5.  
  6. /************************************************************************
  7.  *        Copyright (C) 1989 by Mark B. Phillips                  *
  8.  *                                     *
  9.  * Permission to use, copy, modify, and distribute this software and    *
  10.  * its documentation for any purpose and without fee is hereby granted, *
  11.  * provided that the above copyright notice appear in all copies and    *
  12.  * that both that copyright notice and this permission notice appear in *
  13.  * supporting documentation, and that the name of Mark B. Phillips or   *
  14.  * the University of Maryland not be used in advertising or publicity   *
  15.  * pertaining to distribution of the software without specific, written *
  16.  * prior permission.  This software is provided "as is" without express *
  17.  * or implied warranty.                                                 *
  18.  ************************************************************************/
  19.  
  20. #include <stdio.h>
  21. #include <signal.h>
  22.  
  23. #include "gr.h"
  24. #include "internal.h"
  25. #include "image_info.h"
  26.  
  27. /************************************************************************
  28.  *             PUBLIC DECLARATIONS                *
  29.  ************************************************************************/
  30.  
  31. Frame        GR_anim_frame=NULL;
  32. Panel        GR_anim_panel;
  33. int        GR_interrupted=0;
  34. int        GR_recording_trigger=0;
  35. int        GR_recording_count;
  36.  
  37. /************************************************************************
  38.  *             PRIVATE DECLARATIONS                *
  39.  ************************************************************************/
  40.  
  41. /* Gadgets, etc: */
  42. static Panel_item save_button, play_button, clear_button;
  43. static Panel_item save_sequence_button, delay_slider, done_button;
  44. static Panel_item recording_count_slider, anim_message[2];
  45. static Panel_item playback_count_slider, frames_saved_message;
  46. static Panel_item frames_available_message;
  47. static Menu save_button_menu, save_sequence_button_menu;
  48. static Menu play_button_menu, clear_button_menu;
  49.  
  50. /* Maximum number of frames that can be stored at one time: */
  51. #define MAX_FRAMES 30
  52.  
  53. /* Array of saved frames (pixrects): */
  54. static struct pixrect *saved_pr[MAX_FRAMES];
  55.  
  56. /* Number of currently saved frames: */
  57. static int    frames_saved=0;
  58.  
  59. /* Images for buttons: */
  60. static short save_array[] = {
  61. #include "images/save.image"
  62. };
  63. mpr_static(save_pr, VCB_W, VCB_H, 1, save_array);
  64.  
  65. static short save_sequence_array[] = {
  66. #include "images/save_sequence.image"
  67. };
  68. mpr_static(save_sequence_pr, VCB_W, VCB_H, 1, save_sequence_array);
  69.  
  70. static short clear_array[] = {
  71. #include "images/clear.image"
  72. };
  73. mpr_static(clear_pr, VCB_W, VCB_H, 1, clear_array);
  74.  
  75. static short play_array[] = {
  76. #include "images/play.image"
  77. };
  78. mpr_static(play_pr, VCB_W, VCB_H, 1, play_array);
  79.  
  80. /* Functions: */
  81. static int button_event_proc(), play_button_proc();
  82. static int clear_button_proc(), done_button_proc(), save_button_proc();
  83. static int save_sequence_button_proc(), interrupt_handler();
  84.                                     
  85. /*--------------------End of Private Declarations------------------------*/
  86.  
  87. /************************************************************************
  88.  *              PUBLIC PROCEDURES                *
  89.  ************************************************************************/
  90.  
  91. /*-----------------------------------------------------------------------
  92.  * Function:    GR_show_anim_frame
  93.  * Description:    make the animation frame visible
  94.  * Args:    (none)
  95.  */
  96. int
  97.   GR_show_anim_frame()
  98. {
  99.   if (GR_anim_frame == NULL) initialize_anim_frame();
  100.   GR_anim_message_clear();
  101.   window_set(GR_anim_frame, WIN_SHOW, TRUE, 0);
  102. }
  103.  
  104. /*-----------------------------------------------------------------------
  105.  * Function:    GR_show_anim_message
  106.  * Description:    display a string in one of the anim panel message lines
  107.  * Args  IN:    s: the string
  108.  *        n: message line to use (0 or 1)
  109.  * Notes:    If s is "" the message is cleared
  110.  */
  111. int
  112.   GR_show_anim_message(s,n)
  113. int n;
  114. char *s;
  115. {
  116.   if ((n<0) || (n>1)) return(1);
  117.   return(GR_show_message(anim_message[n], s, GR_ANIM_MESSAGE_LENGTH));
  118. }
  119.  
  120. /*-----------------------------------------------------------------------
  121.  * Function:    GR_show_anim_error
  122.  * Description:    same as GR_show_anim_message, but beeps bell
  123.  */
  124. int
  125.   GR_show_anim_error(s,n)
  126. int n;
  127. char *s;
  128. {
  129.   if ((n<0) || (n>1)) return(1);
  130.   window_bell(GR_anim_panel);
  131.   return(GR_show_message(anim_message[n], s, GR_ANIM_MESSAGE_LENGTH));
  132. }
  133.  
  134. /*-----------------------------------------------------------------------
  135.  * Function:    GR_anim_message_clear
  136.  * Description:    clear all messages in anim panel
  137.  */
  138. int
  139.   GR_anim_message_clear()
  140. {
  141.  GR_show_anim_message("",0);
  142.  GR_show_anim_message("",1);
  143. }
  144.  
  145. /*-----------------------------------------------------------------------
  146.  * Function:    GR_save_frame
  147.  * Description:    save a frame
  148.  */
  149. int
  150.   GR_save_frame()
  151. {
  152.   GR_anim_message_clear();
  153.   if (frames_saved >= MAX_FRAMES) {
  154.     GR_show_anim_error("No more frames available !",0);
  155.     return;
  156.   }
  157.   saved_pr[frames_saved] =
  158.     mem_create(GR_canvas_pw->pw_pixrect->pr_size.x,
  159.            GR_canvas_pw->pw_pixrect->pr_size.y, 1);
  160.   if (saved_pr[frames_saved]==NULL) {
  161.     GR_error("No memory left to store frames !");
  162.     GR_interrupted=1;
  163.     return;
  164.   }
  165.   pw_read(saved_pr[frames_saved], 0, 0,
  166.       saved_pr[frames_saved]->pr_size.x, saved_pr[frames_saved]->pr_size.y,
  167.       PIX_SRC, GR_canvas_pw, 0, 0);
  168.   set_frame_number_displays(++frames_saved);
  169. }
  170.  
  171. /************************************************************************
  172.  *              PRIVATE PROCEDURES                *
  173.  ************************************************************************/
  174.  
  175. /*-----------------------------------------------------------------------
  176.  * Function:    initialize_anim_frame
  177.  * Description:    create and initialize animation frame and its subwindows
  178.  * Args:    (none)
  179.  */
  180. static int
  181.   initialize_anim_frame()
  182. {
  183.   int i;
  184.   
  185.   GR_anim_frame =
  186.     window_create(GR_base_frame, FRAME,
  187.           WIN_X, 462,
  188.           WIN_Y, 0,
  189.           FRAME_SHOW_LABEL, TRUE,
  190.           FRAME_LABEL, "Animation",
  191.           0);
  192.   if (GR_anim_frame == NULL) {
  193.     GR_error("Can't create any more windows !");
  194.     return(1);
  195.   }
  196.   
  197.   GR_anim_panel =
  198.     window_create(GR_anim_frame, PANEL,
  199.           WIN_X, 0,
  200.           WIN_Y, 0,
  201.           WIN_WIDTH, 370,
  202.           WIN_HEIGHT, 223,
  203.           0);
  204.   if (GR_anim_panel == NULL) {
  205.     GR_error("Can't create any more windows !");
  206.     window_destroy(GR_anim_frame);
  207.     return(1);
  208.   }
  209.   
  210.   save_button =
  211.     panel_create_item(GR_anim_panel, PANEL_BUTTON, 
  212.               PANEL_ITEM_X, 5,
  213.               PANEL_ITEM_Y, 5,
  214.               PANEL_LABEL_IMAGE, &save_pr,
  215.               PANEL_NOTIFY_PROC, save_button_proc,
  216.               PANEL_EVENT_PROC, button_event_proc,
  217.               0);
  218.   save_button_menu =
  219.     menu_create(MENU_STRINGS, "Save Frame", 0, 0);
  220.   
  221.   play_button =
  222.     panel_create_item(GR_anim_panel, PANEL_BUTTON, 
  223.               PANEL_ITEM_X, 5,
  224.               PANEL_ITEM_Y, 111,
  225.               PANEL_LABEL_IMAGE, &play_pr,
  226.               PANEL_NOTIFY_PROC, play_button_proc,
  227.               PANEL_EVENT_PROC, button_event_proc,
  228.               0);
  229.   play_button_menu =
  230.     menu_create(MENU_STRINGS, "Play Back Saved Frames", 0, 0);
  231.   
  232.   clear_button =
  233.     panel_create_item(GR_anim_panel, PANEL_BUTTON, 
  234.               PANEL_ITEM_X, 241,
  235.               PANEL_ITEM_Y, 5,
  236.               PANEL_LABEL_IMAGE, &clear_pr,
  237.               PANEL_NOTIFY_PROC, clear_button_proc,
  238.               PANEL_EVENT_PROC, button_event_proc,
  239.               0);
  240.   clear_button_menu =
  241.     menu_create(MENU_STRINGS, "Clear Saved Frames", 0, 0);
  242.  
  243.   delay_slider =
  244.     panel_create_item(GR_anim_panel, PANEL_SLIDER, 
  245.               PANEL_ITEM_X, 64,
  246.               PANEL_ITEM_Y, 118,
  247.               PANEL_LABEL_STRING, "Interframe Delay (millisecs)",
  248.               PANEL_VALUE, 0, 
  249.               PANEL_SLIDER_WIDTH, 100, 
  250.               PANEL_MIN_VALUE, 0, 
  251.               PANEL_MAX_VALUE, 5000, 
  252.               PANEL_LAYOUT, PANEL_VERTICAL,
  253.               0);
  254.   
  255.   done_button =
  256.     panel_create_item(GR_anim_panel, PANEL_BUTTON, 
  257.               PANEL_ITEM_X, 304,
  258.               PANEL_ITEM_Y, 10,
  259.               PANEL_LABEL_IMAGE,
  260.                 panel_button_image(GR_anim_panel, "Done", 5, 0),
  261.               PANEL_NOTIFY_PROC, done_button_proc,
  262.               PANEL_EVENT_PROC, button_event_proc,
  263.               0);
  264.   
  265.   playback_count_slider =
  266.     panel_create_item(GR_anim_panel, PANEL_SLIDER, 
  267.               PANEL_ITEM_X, 224,
  268.               PANEL_ITEM_Y, 64,
  269.               PANEL_LABEL_STRING, " Playback Count",
  270.               PANEL_VALUE, 1, 
  271.               PANEL_SLIDER_WIDTH, MAX_FRAMES, 
  272.               PANEL_MIN_VALUE, 1, 
  273.               PANEL_MAX_VALUE, MAX_FRAMES, 
  274.               PANEL_LAYOUT, PANEL_VERTICAL,
  275.               0);
  276.   
  277.   recording_count_slider =
  278.     panel_create_item(GR_anim_panel, PANEL_SLIDER, 
  279.               PANEL_ITEM_X, 64,
  280.               PANEL_ITEM_Y, 64,
  281.               PANEL_LABEL_STRING, "Recording Count",
  282.               PANEL_VALUE, 0, 
  283.               PANEL_SLIDER_WIDTH, MAX_FRAMES, 
  284.               PANEL_MIN_VALUE, 0, 
  285.               PANEL_MAX_VALUE, MAX_FRAMES, 
  286.               PANEL_LAYOUT, PANEL_VERTICAL,
  287.               0);
  288.   
  289.   save_sequence_button =
  290.     panel_create_item(GR_anim_panel, PANEL_BUTTON, 
  291.               PANEL_ITEM_X, 5,
  292.               PANEL_ITEM_Y, 58,
  293.               PANEL_LABEL_IMAGE, &save_sequence_pr,
  294.               PANEL_NOTIFY_PROC, save_sequence_button_proc,
  295.               PANEL_EVENT_PROC, button_event_proc,
  296.               0);
  297.   save_sequence_button_menu =
  298.     menu_create(MENU_STRINGS, "Save Sequence of Frames", 0, 0);
  299.   
  300.   anim_message[0] =
  301.     panel_create_item(GR_anim_panel, PANEL_MESSAGE, 
  302.               PANEL_ITEM_X, 10,
  303.               PANEL_ITEM_Y, 172,
  304.               PANEL_LABEL_STRING, "",
  305.               PANEL_LABEL_FONT, GR_bold_font,
  306.               0);
  307.   
  308.   anim_message[1] =
  309.     panel_create_item(GR_anim_panel, PANEL_MESSAGE, 
  310.               PANEL_ITEM_X, 10,
  311.               PANEL_ITEM_Y, 195,
  312.               PANEL_LABEL_STRING, "",
  313.               PANEL_LABEL_FONT, GR_bold_font,
  314.               0);
  315.   
  316.   panel_create_item(GR_anim_panel, PANEL_MESSAGE, 
  317.             PANEL_ITEM_X, 95,
  318.             PANEL_ITEM_Y, 7,
  319.             PANEL_LABEL_STRING, "Frames Saved:",
  320.             PANEL_LABEL_BOLD, 0,
  321.             0);
  322.   
  323.   frames_saved_message =
  324.     panel_create_item(GR_anim_panel, PANEL_MESSAGE, 
  325.               PANEL_ITEM_X, 208,
  326.               PANEL_ITEM_Y, 7,
  327.               PANEL_LABEL_STRING, "",
  328.               0);
  329.   
  330.   panel_create_item(GR_anim_panel, PANEL_MESSAGE, 
  331.             PANEL_ITEM_X, 64,
  332.             PANEL_ITEM_Y, 25,
  333.             PANEL_LABEL_STRING, "Frames Available:",
  334.             0);
  335.  
  336.   frames_available_message =
  337.     panel_create_item(GR_anim_panel, PANEL_MESSAGE, 
  338.               PANEL_ITEM_X, 208,
  339.               PANEL_ITEM_Y, 25,
  340.               PANEL_LABEL_STRING, "",
  341.               PANEL_LABEL_BOLD, 0,
  342.               0);
  343.  
  344.   window_fit(GR_anim_frame);
  345.   set_frame_number_displays(0);
  346.   notify_set_signal_func(GR_base_frame, interrupt_handler,
  347.              SIGURG, NOTIFY_ASYNC);
  348.   for (i=0; i<MAX_FRAMES; ++i)
  349.     saved_pr[i] = NULL;
  350. }
  351.  
  352. /*-----------------------------------------------------------------------
  353.  * Function:    button_event_proc
  354.  * Description:    respond to a button
  355.  * Args  IN:    item: handle of button which received event
  356.  *        event: the event
  357.  * Notes:    Display's button's menu if appropriate
  358.  */
  359. static int
  360.   button_event_proc(item, event)
  361. Panel_item item;
  362. Event *event;
  363. {
  364.   /* If event is right mouse button going down, display button's menu */
  365.   if ( (event_id(event)==MS_RIGHT) && (event_is_down(event)) ) {
  366.     
  367.     if (item == save_sequence_button)
  368.       menu_show(save_sequence_button_menu, GR_anim_panel, event, 0);
  369.     else if (item == save_button)
  370.       menu_show(save_button_menu, GR_anim_panel, event, 0);
  371.     else if (item == play_button)
  372.       menu_show(play_button_menu, GR_anim_panel, event, 0);
  373.     else if (item == clear_button)
  374.       menu_show(clear_button_menu, GR_anim_panel, event, 0);
  375.     
  376.     /* Then move mouse cursor back to where it was before menu display */
  377.     window_set((Panel)panel_get(item, PANEL_PARENT_PANEL),
  378.            WIN_MOUSE_XY, event_x(event), event_y(event),
  379.            0);
  380.   }
  381.   
  382.   /* Otherwise, do the normal thing for this button */
  383.   else
  384.     panel_default_handle_event(item, event);
  385. }
  386.  
  387. /*-----------------------------------------------------------------------
  388.  * Function:    save_button_proc
  389.  * Description:    save a frame (save button's notify proc)
  390.  */
  391. static int
  392.   save_button_proc()
  393. {
  394.   GR_save_frame();
  395. }
  396.  
  397. /*-----------------------------------------------------------------------
  398.  * Function:    play_button_proc
  399.  * Description:    play back saved frames
  400.  */
  401. static int
  402.   play_button_proc()
  403. {
  404.   int n, repeat_count, frame;
  405.   unsigned interframe_delay;
  406.   char msg[GR_ANIM_MESSAGE_LENGTH+1];
  407.  
  408.   GR_anim_message_clear();
  409.   if (frames_saved == 0) {
  410.     GR_show_anim_error("No frames have been saved !",0);
  411.     return;
  412.   }
  413.  
  414.   repeat_count = (int)panel_get_value(playback_count_slider);
  415.   interframe_delay = 1000 * (unsigned)panel_get_value(delay_slider);
  416.  
  417.   GR_interrupted=0;
  418.   GR_show_error_message("Hit the STOP key (L1) to interrupt the movie");
  419.   for (n=0; (n<repeat_count) && (!GR_interrupted); ++n) {
  420.     for (frame=0; (frame<frames_saved) && (!GR_interrupted); ++frame) {
  421.       sprintf(msg,"Displaying Frame %2d", frame+1);
  422.       GR_show_anim_message(msg,0);
  423.       pw_batch_on(GR_canvas_pw);
  424.       pw_write(GR_canvas_pw, 0, 0,
  425.            saved_pr[frame]->pr_size.x, saved_pr[frame]->pr_size.y,
  426.            PIX_SRC, saved_pr[frame], 0, 0);
  427.       pw_batch_off(GR_canvas_pw);
  428.       if ((!GR_interrupted) && (interframe_delay != 0))
  429.     usleep(interframe_delay);
  430.     }
  431.   }
  432.   GR_anim_message_clear();
  433.   GR_show_error_message("");
  434.   if (GR_interrupted)
  435.     GR_show_anim_message("Playback interrupted",0);
  436.   else
  437.     GR_show_anim_message("Playback finished",0);
  438. }
  439.  
  440. /*-----------------------------------------------------------------------
  441.  * Function:    clear_button_proc
  442.  * Description:    clear all saved frames
  443.  */
  444. static int
  445.   clear_button_proc()
  446. {
  447.   int frame;
  448.  
  449.   GR_anim_message_clear();
  450.   for (frame=0; frame<frames_saved; ++frame) {
  451.       pr_destroy(saved_pr[frame]);
  452.       saved_pr[frame] = NULL;
  453.     }
  454.   set_frame_number_displays(frames_saved=0);
  455.   GR_show_anim_message("Frames cleared",0);
  456. }
  457.  
  458. /*-----------------------------------------------------------------------
  459.  * Function:    save_sequence_button_proc
  460.  * Description:    save a sequence of frames
  461.  * Notes:    This proc just sets a flag (GR_recording trigger) and then
  462.  *        returns.  The view control buttons test for this flag and
  463.  *        behave differently if it has been set.
  464.  */
  465. static int
  466.   save_sequence_button_proc()
  467. {
  468.   char msg[GR_ANIM_MESSAGE_LENGTH+1];
  469.  
  470.   GR_anim_message_clear();
  471.  
  472.   if (GR_recording_trigger) {
  473.     GR_show_anim_message("Recording sequence canceled",0);
  474.     GR_recording_trigger=0;
  475.     return;
  476.   }
  477.  
  478.   GR_recording_count = (int)panel_get_value(recording_count_slider);
  479.   if (GR_recording_count+frames_saved > MAX_FRAMES) {
  480.     sprintf(msg,"No space for %1d more frames",GR_recording_count);
  481.     GR_show_anim_error(msg,0);
  482.     GR_show_anim_message("(Decrease count or clear frames)",1);
  483.     return;
  484.   }
  485.   GR_recording_trigger=1;
  486.   GR_show_anim_message("Select view button for sequence ...",0);
  487.   GR_show_anim_message("(Pick sequence button again to cancel)",1);
  488. }
  489.  
  490. /*-----------------------------------------------------------------------
  491.  * Function:    done_button_proc
  492.  * Description:    notify procedure for "Done" button
  493.  * Args:    (none)
  494.  * Notes:    makes animaton frame disappear, but does not destroy it
  495.  */
  496. static int
  497.   done_button_proc()
  498. {
  499.   window_set(GR_anim_frame, WIN_SHOW, FALSE, 0);
  500. }
  501.  
  502. /*-----------------------------------------------------------------------
  503.  * Function:    set_frame_number_displays
  504.  * Description:    set the display of the number of saved and available
  505.  *          frames
  506.  * Args  IN:    saved: the number of saved frames
  507.  * Notes:    number available is MAX_FRAMES-saved
  508.  */
  509. static int
  510.   set_frame_number_displays(saved)
  511. int saved;
  512. {
  513.   char buf[3];
  514.  
  515.   sprintf(buf, "%2d", saved);
  516.   panel_set(frames_saved_message, PANEL_LABEL_STRING, buf, 0);
  517.   sprintf(buf, "%2d", MAX_FRAMES-saved);
  518.   panel_set(frames_available_message, PANEL_LABEL_STRING, buf, 0);
  519. }
  520.  
  521. /*-----------------------------------------------------------------------
  522.  * Function:    interrupt_handler
  523.  * Description:    handler for SIGURG, which is generate by STOP (L1) key 
  524.  * Notes:    Just set a flag and return.  Other pieces of program
  525.  *        check for this flag.
  526.  */
  527. static int
  528.   interrupt_handler()
  529. {
  530.   ++GR_interrupted;
  531. }
  532.  
  533.